package com.ht.module.sys.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ht.abnormal.HtException;
import com.ht.config.dataAuth.DataScope;
import com.ht.constant.DicConstants;
import com.ht.constant.RedisConstants;
import com.ht.module.sys.dto.UpdatePasswordDto;
import com.ht.module.sys.entity.SysMenu;
import com.ht.module.sys.entity.SysUser;
import com.ht.module.sys.entity.SysUserRole;
import com.ht.module.sys.mapper.SysMenuMapper;
import com.ht.module.sys.mapper.SysUserMapper;
import com.ht.module.sys.mapper.SysUserRoleMapper;
import com.ht.module.sys.service.ISysMenuService;
import com.ht.module.sys.service.ISysUserRoleService;
import com.ht.module.sys.service.ISysUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ht.module.sys.vo.SysUser.*;
import com.ht.util.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Auto-generator
 * @since 2021-04-27
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {
    @Resource
    private SysMenuMapper sysMenuMapper;
    @Resource
    private SysUserRoleMapper sysUserRoleMapper;
    @Resource
    private ISysUserRoleService iSysUserRoleService;
    @Resource
    private ISysMenuService iSysMenuService;
    @Resource
    private BCryptPasswordEncoder passwordEncoder;
    @Value("${password}")
    private String password;
    //过期时间
    @Value("${jwt.expireTime}")
    public long EXPIRE_TIME;
    @Resource
    private RedisUtil redisUtil;


    @Override
    public SysUser getUserInfoByUsername(String username) {
        QueryWrapper<SysUser> qw = new QueryWrapper<>();
        qw.eq("username", username);
        return baseMapper.selectOne(qw);
    }

    @Override
    public SysUser getUserInfoByUsernameAll(String username) {
        QueryWrapper<SysUser> qw = new QueryWrapper<>();
        qw.eq("username", username);
        return getUserByid(baseMapper.selectOne(qw).getId());
    }

    @Override
    public SysUser getUserByid(String id) {
        SysUser sysUser = baseMapper.selectById(id);
        //获取用户按钮权限和菜单权限
        List<SysMenu> sysMenuList = sysMenuMapper.findByUserId(sysUser.getId());
        //设置用户按钮权限
        sysUser.setPermissions(sysMenuList.stream().filter(x -> x.getType().equals("2")).collect(Collectors.toList()));
        //设置用户菜单权限
        sysUser.setSysMenus(iSysMenuService.buildTree(
               sysMenuList.stream()
                       .filter(x->!x.getType().equals(DicConstants.MenuType.BUTTON))
                       .collect(Collectors.toList()),
                "0"
        ));
        sysUser.setSysMenusNoTree(sysMenuList);

        //获取用户角色对象
        sysUser.setRoleObjs(sysUserRoleMapper.findRoleByUserId(id));
        //获取用户角色id
        sysUser.setRoles(sysUser.getRoleObjs().stream().map(x->x.getId()).collect(Collectors.toList()));

        return sysUser;
    }

    @Override
    public SysUser getLoginUser(Principal principal) {
        return UserUtil.getUser();
    }

    @Override
    public Pager<SysUser> findPage(Pager<SysUser> pager, SysUser en) {
        QueryWrapper<SysUser> qw=new QueryWrapper<>();
        if(StrUtil.isNotEmpty(en.getUsername())){
            qw.like("tab.username",en.getUsername());
        }
        if(StrUtil.isNotEmpty(en.getName())){
            qw.like("tab.name",en.getName());
        }
        if(StrUtil.isNotEmpty(en.getRoleNames())){
            qw.like("tab.role_names",en.getRoleNames());
        }
        return baseMapper.findPageAuth(pager,qw,new DataScope().initOrder(pager));
    }

    @Override
    public void saveObj(SysUser sysUser) {
        //判断当前用户是否存在
        if(this.getUserInfoByUsername(sysUser.getUsername())!=null){
            throw new HtException("当前用户已经存在！");
        }
        sysUser.setCreateDate(LocalDateTime.now());
        sysUser.setCreateUser(UserUtil.getUserId());
        sysUser.setPassword( passwordEncoder.encode(password));
        this.save(sysUser);
    }

    @Override
    public void resetPassword(String id) {
        //获取当前用户
        SysUser sysUser=baseMapper.selectById(id);
        sysUser.setPassword(passwordEncoder.encode(password));
        baseMapper.updateById(sysUser);
    }

    @Override
    @Transactional
    public void setRoles(SysUser sysUser) {
        //删除用户原本的角色
        sysUserRoleMapper.delete(new QueryWrapper<SysUserRole>().eq("user_id",sysUser.getId()));
        //增加新的角色
        iSysUserRoleService.saveBatch(sysUser.getRoles().stream().map(x->{
            SysUserRole item=new SysUserRole();
            item.setUserId(sysUser.getId());
            item.setRoleId(x);
            return item;
        }).collect(Collectors.toList()));
        //删除权限缓存
        redisUtil.del(RedisConstants.DATA_AUTHORITY + sysUser.getId());
    }

    @Override
    public void updatePassword(UpdatePasswordDto en) {
        if (!en.getPassword().equals(en.getConfirmPassword())) {
            throw new HtException("两次密码不一样！");
        }
        //判断旧的密码是否正确
        if (!passwordEncoder.matches(en.getOldPassword(), UserUtil.getUser().getPassword())) {
            throw new HtException("旧的密码不正确！");
        }
        SysUser sysUser = new SysUser().setId(UserUtil.getUserId()).setPassword(passwordEncoder.encode(en.getPassword()));
        //修改
        this.updateById(sysUser);
    }

    @Override
    public void updateState(String id, String val) {
        SysUser sysUser=new SysUser();
        sysUser.setId(id);
        sysUser.setState(val);
        CommMethod.beanUpdate(sysUser);
        baseMapper.updateById(sysUser);
    }

    @Override
    public UserLoginVo loginUser(String userName) {
        SysUser sysUser=getUserInfoByUsernameAll(userName);
        //吧用户信息存到token里面
        Map<String, Object> jwtMap=new HashMap<>();
        jwtMap.put("id",sysUser.getId());                   //设置用户id
        jwtMap.put("deptId",sysUser.getDeptId());           //设置部门id
        jwtMap.put("username",sysUser.getUsername());       //设置用户名
        String jwtToken = JwtUtils.sign(jwtMap);

        //将当前用户的权限缓存下来
        Map<String,String> roleMap=new HashMap<>();
        //设置角色权限
        roleMap.put(RedisConstants.SYS_ROLE_CODES, String.join(",", sysUser.getRoles()));
        //设置菜单
        roleMap.put(RedisConstants.SYS_MENU_CODES,sysUser.getSysMenusNoTree().stream().map(SysMenu::getCode).collect(Collectors.joining(",")));

        //将用户信息存到redis
        redisUtil.set(RedisConstants.USER_INFOS_PREFIX+jwtToken,jwtMap,EXPIRE_TIME);
        //将用户权限信息存到redis
        redisUtil.set(RedisConstants.USER_ROLE+sysUser.getUsername(),roleMap,EXPIRE_TIME);
        //吧用户信息返回给前端
        UserLoginVo vo=new UserLoginVo().setToken(jwtToken).setUserInfo(sysUser);
        return  vo;
    }

    @Override
    public void editById(SysUser sysUser) {
        baseMapper.updateById(sysUser);
    }

}
